package com.novax.ex.activity.provider.service;

import com.alibaba.fastjson.JSON;
import com.novax.ex.activity.infrastructure.entity.BeebUser;
import com.novax.ex.activity.infrastructure.mapper.BeebUserMapper;
import com.novax.ex.activity.open.model.query.BeebUserQuery;
import com.novax.ex.activity.provider.api.InternalTransferOrderApi;
import com.novax.ex.activity.provider.api.model.BeebInternalOrderResponse;
import com.novax.ex.activity.provider.api.model.BeebMaxMinIdsResponse;
import com.novax.ex.activity.provider.common.BinlogUtils;
import com.novax.ex.activity.provider.handler.provider.BeebInternalOrderProvider;
import com.novax.ex.common.results.ReturnResult;
import com.novax.ex.common.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.atomic.LongAdder;

/**
 * @Description
 * @Author zhaolei
 * @Date 10/24/24 2:47 PM
 * @Version 1.0
 */
@Slf4j
@Service
public class InternalTransferOrderBigdataService {
    @Resource
    private BeebUserMapper beebUserMapper;
    @Resource
    private InternalTransferOrderApi internalTransferOrderApi;
    @Resource
    private BeebInternalOrderProvider beebInternalOrderProvider;
    @Resource
    private BeebActivityBService beebActivityBService;

    public static LongAdder sendCount = new LongAdder();//发送计数器
    public static LongAdder receiveCount = new LongAdder();//接收计数器

    public static Set<String> binLogTypeSet = new HashSet<>(Arrays.asList("INSERT", "UPDATE"));
    public static String tableName = "internal_transfer_order";

    static Long beebUserId = 28629862l;//由项目方提供的用户id
    static BigDecimal transferAmount = BigDecimal.TEN;//最低需要转入的金额
    static Integer batchSize = new BigDecimal("1000").divide(new BigDecimal("3"), 0, BigDecimal.ROUND_DOWN).intValue();//总批次

    /**
     * beeb项目相关整理后的最终方案:
     * 1.按照价值10%加入解锁,包括历史数据处理(从11月8日-11月9日结束)
     * 举例子:公式为1000*0.1*0.1=10u,用户转入10u,就能满足解锁1000的beeb,用户一次性转入必须符合转入的u>=按照币折算的U，且要大于等于10U
     * (1.11月8日有用户按照10%这个转入了指定账户28629862,上线后需要进行初始化跑数据,将符合要求的用户加入到解锁）
     * (2.实时处理用户转账,如果符合要求进行加入到解锁）
     * 2.程序去掉卖币的比如转账到xxx账户,按照0.1进行加入到新的方案中的代码
     * 3.处理历史10U问题,需要程序到时候按照转入价值,算出来需要给用户beeb数量自动发放到可用,具体后面在定,但是截止时间为我们程序上线之后的这一段数据
     **/
    //给定方案B的时间
    //static Date bTime = DateUtil.stringToDate("2024-11-08 00:00:00");
    //curl -X GET -H "Accept:/" -H "Content-Type:application/x-www-form-urlencoded" "http://localhost:51041/v3/private/beeb/unlock/init?startTime=2024-10-20&pageSize=1000"
    public void init(BeebUserQuery query) {
        //获取批次开始时间
        String startTime = query.getStartTime();
        if (Objects.isNull(startTime)) {
            startTime = "2024-10-20 00:00:00";
        }
        //拉取数据
        initData(startTime, query.getPageSize());
    }

    public void initData(String time, Long pageSize) {
        if (StringUtils.isBlank(time)) {
            time = DateUtil.getDateStringSeq(new Date(), DateUtil.DEFAULT_DATE);
        }
        Long idStart = 0l;
        Long idEnd = 0l;
        int size = 0;
        ReturnResult<BeebMaxMinIdsResponse> beebMinMaxIds = internalTransferOrderApi.getBeebMinMaxIds(time);
        if (beebMinMaxIds.isSuccess()) {
            idStart = beebMinMaxIds.getData().getMin() - 1;
            idEnd = beebMinMaxIds.getData().getMax();
            log.info("本批次数据起止:--idStart:" + idStart + "--idEnd:" + idEnd);
        }
        Instant start = Instant.now();
        while (idStart < idEnd) {
            ReturnResult<List<BeebInternalOrderResponse>> beebData = internalTransferOrderApi.getBeebData(idStart, pageSize);
            if (beebData.isSuccess()) {
                List<BeebInternalOrderResponse> list = beebData.getData();
                if (Objects.isNull(list) || list.size() == 0) {
                    idStart = idEnd;
                } else {
                    idStart = list.get(list.size() - 1).getId();
                    initOld(list);
                }
                size = size + list.size();
            }
            log.info("当前截止Id:" + idStart);
            try {
                Thread.sleep(1000);
            } catch (Exception ex) {

            }
        }
        log.info("初始化拉取处理完毕:" + DateUtil.getDateStringSeq(new Date(), DateUtil.DEFAULT_TIME) +
                "--发送总数:" + size +
                "--耗时:" + Duration.between(start, Instant.now()).toMillis() + " milliseconds"
        );
    }

    private void initOld(List<BeebInternalOrderResponse> dataList) {
        for (BeebInternalOrderResponse userResponse : dataList) {
            sendCount.increment();
            beebInternalOrderProvider.sendMsgHistory(userResponse.getId().toString(), JSON.toJSONString(userResponse));
        }
    }


    public void execBigData(String msg) {
        List<LinkedHashMap<String, String>> data = BinlogUtils.getData(msg, binLogTypeSet, tableName);
        if (Objects.nonNull(data)) {
            for (LinkedHashMap<String, String> datum : data) {
                /**
                 CREATE TABLE `internal_transfer_order` (
                 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
                 `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID',
                 `from_user_id` bigint(20) unsigned NOT NULL COMMENT '账户的uid',
                 `account_type` int(2) NOT NULL COMMENT '账户类型:1=uid,2=手机号,3=email',
                 `account` varchar(256) NOT NULL DEFAULT '' COMMENT '账户：uid,手机号,email',
                 `account_user_id` bigint(20) unsigned NOT NULL COMMENT '账户的uid',
                 `currency` varchar(20) NOT NULL COMMENT '币种名称',
                 `amount` decimal(50,20) unsigned NOT NULL COMMENT '交易数量',
                 `new_price` decimal(50,20) unsigned NOT NULL DEFAULT '0.00000000000000000000' COMMENT '最新价',
                 `fee` decimal(50,20) DEFAULT '0.00000000000000000000' COMMENT '手续费',
                 `total` decimal(50,20) unsigned NOT NULL COMMENT '交易总数量',
                 `type` int(2) NOT NULL COMMENT '交易类型：1=站内充值,2=站内提币',
                 `status` int(2) NOT NULL COMMENT '状态:1=下单（待审核）,2=确认,3=驳回,4=暂不处理',
                 `reject_reason` varchar(256) DEFAULT NULL COMMENT '驳回原因',
                 `exception_reason` varchar(256) DEFAULT NULL COMMENT '暂不处理原因',
                 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                 `updater` bigint(12) DEFAULT NULL COMMENT '更新人id',
                 `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
                 `is_collect` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否收藏 0：不收藏 1：收藏',
                 `latest_notes` varchar(1024) DEFAULT NULL COMMENT '最新备注',
                 PRIMARY KEY (`id`) USING BTREE,
                 KEY `idx_user_id` (`user_id`) USING BTREE,
                 KEY `idx_account` (`account`) USING BTREE,
                 KEY `idx_ctime` (`create_time`) USING BTREE,
                 KEY `idx_utime` (`update_time`) USING BTREE,
                 KEY `idx_currency` (`currency`)
                 ) ENGINE=InnoDB AUTO_INCREMENT=127 DEFAULT CHARSET=utf8mb4 COMMENT='站内转账订单';
                 **/
                String id = datum.get("id"); // id
                String user_id = datum.get("user_id"); // 接受人的id
                String from_user_id = datum.get("from_user_id");// 谁发起的
                String currency = datum.get("currency");//币种
                String amount = datum.get("amount");//单次的数量
                String type = datum.get("type");//类型为1 站内充值
                String status = datum.get("status");//2=确认
                String update_time = datum.get("update_time");//时间
                log.info(id + "--" + user_id + "--" + from_user_id + "--" + currency + "--" + amount + "--" + type + "--" + status + "--" + update_time);
                //exec(user_id, from_user_id, currency, amount, type, status);
                BeebInternalOrderResponse response = new BeebInternalOrderResponse();
                response.setId(Long.parseLong(id));
                response.setUserId(user_id == null ? null : Long.parseLong(user_id));
                response.setFromUserId(from_user_id == null ? null : Long.parseLong(from_user_id));
                response.setCurrency(currency == null ? null : currency);
                response.setAmount(amount == null ? null : new BigDecimal(amount));
                response.setType(type == null ? null : Integer.parseInt(type));
                response.setStatus(status == null ? null : Integer.parseInt(status));
                response.setUpdateTime(update_time);
                beebInternalOrderProvider.sendMsg(response.getId().toString(), JSON.toJSONString(response));
            }
        }
    }

    @Transactional(rollbackFor = RuntimeException.class)
    public void exec(String msg) {
        //条件校验
        receiveCount.increment();
        BeebInternalOrderResponse entity = JSON.parseObject(msg, BeebInternalOrderResponse.class);
        if (check(entity)) {
            //说明是需要进行处理的
            //查询数据
            List<BeebUser> beebUsers = beebUserMapper.queryByUserId(entity.getFromUserId());
            if (Objects.nonNull(beebUsers) && beebUsers.size() > 0) {
                for (BeebUser beebUser : beebUsers) {
                    if (checkData(beebUser)) {
                        //处理是否满足最新需求方案b，按照转入金额大于持有市值10%进行
                        if (checkB(beebUser, entity)) {
                            BeebUser nbeebUser = new BeebUser();
                            nbeebUser.setId(beebUser.getId());
                            /**
                             * 每批次解锁量
                             */
                            nbeebUser.setUnlockBatchTotal(beebUser.getSendTotal().divide(new BigDecimal(batchSize + ""), 8, BigDecimal.ROUND_DOWN));

                            /**
                             * 总批次
                             */
                            nbeebUser.setUnlockBatch(batchSize);

                            /**
                             * 0:不符合解锁条件 1:解锁中 2:解锁完毕
                             */
                            nbeebUser.setStatus(1);
                            beebUserMapper.updateByPrimaryKeySelective(nbeebUser);
                        }
                    }
                }
            }
        }
        //在调用方案b的
        //beebActivityBService.exec(entity);
    }

    //数据检查
    private boolean checkData(BeebUser beebUser) {
        boolean b = false;
        if (beebUser.getSendStatus().equals(1)
                &&
                beebUser.getStatus().equals(0)
        ) {
            b = true;
        }
        return b;
    }

    //条件检查过滤
    private boolean check(BeebInternalOrderResponse entity) {
        if (entity.getUserId().equals(beebUserId)
                && entity.getCurrency().equals("usdt")
                && entity.getType().equals(1)
                && entity.getStatus().equals(2)
                && entity.getAmount().compareTo(transferAmount) > -1
        ) {
            return true;
        }
        return false;
    }

    //数据检查 方案b是否满足
    private boolean checkB(BeebUser beebUser, BeebInternalOrderResponse entity) {
        //判断当前时间是否小于给定的时间，如果是那么直接按照老的规则返回true，
        boolean b = false;
        /*if (bTime.compareTo(DateUtil.stringToDate(entity.getUpdateTime())) == 1) {
            //说明订单上的时间<指定时间。按照老方案走
            b = true;
        } else {*/
        //如果当前时间大于给定时间那么算一下当前发放的数量*0.1<=转账金额，如果满足返回true
        //已发放到冻结的币，转U，按照10%的比例折算
        BigDecimal sendU = beebUser.getSendTotal().multiply(new BigDecimal("0.01"));
        if (entity.getAmount().compareTo(sendU) > -1) {
            b = true;
        }
        //}
        return b;
    }

    /*public static void main(String[] args) {
        //Integer batchSize = new BigDecimal("1000").divide(new BigDecimal("3"), 0, BigDecimal.ROUND_DOWN).intValue();//总批次
        //System.out.println(batchSize);

        Date st = DateUtil.stringToDate("2024-11-05 00:00:00");
        Date st1 = DateUtil.stringToDate("2024-11-05 01:00:00");
        System.out.println(st.compareTo(st1));
    }*/

    /********************************* 新需求 *****************************************/
    /**
     * 新需求：
     * 从10月20日截止到11月20日，所有收到冻结状态的beeb代币的用户且该用户还没有进入到解锁队列中，
     * 并且在这期间有一次内部转账金额大于等于10U的这部分用户，将会被自动放入到解锁队列中。
     **/

    @Transactional(rollbackFor = RuntimeException.class)
    public void execHistory(String msg) {
        //条件校验
        receiveCount.increment();
        BeebInternalOrderResponse entity = JSON.parseObject(msg, BeebInternalOrderResponse.class);
        if (check(entity)) {
            //说明是需要进行处理的
            //查询数据
            List<BeebUser> beebUsers = beebUserMapper.queryByUserId(entity.getFromUserId());
            if (Objects.nonNull(beebUsers) && beebUsers.size() > 0) {
                for (BeebUser beebUser : beebUsers) {
                    if (checkData(beebUser)) {
                        BeebUser nbeebUser = new BeebUser();
                        nbeebUser.setId(beebUser.getId());
                        /**
                         * 每批次解锁量
                         */
                        nbeebUser.setUnlockBatchTotal(beebUser.getSendTotal().divide(new BigDecimal(batchSize + ""), 8, BigDecimal.ROUND_DOWN));

                        /**
                         * 总批次
                         */
                        nbeebUser.setUnlockBatch(batchSize);

                        /**
                         * 0:不符合解锁条件 1:解锁中 2:解锁完毕
                         */
                        nbeebUser.setStatus(1);
                        beebUserMapper.updateByPrimaryKeySelective(nbeebUser);
                    }
                }
            }
        }
        //在调用方案b的
        //beebActivityBService.exec(entity);
    }
}
